package com.jonlandrum.selfbalancingtree.avltree;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.jonlandrum.selfbalancingtree.Node;

public class AVLTreeTest {
    private AVLTree<String> tree;
    
    @Before
    public void init() {
        tree = new AVLTree<String>();
    }
    
    @After
    public void destroy() {
        tree = null;
    }
    
    @Test
    public void testConstructorNull() {
        assertThat(tree, instanceOf(AVLTree.class));
    }
    
    @Test
    public void testConstructorString() {
        tree = new AVLTree<String>("Root");
        assertThat(tree, instanceOf(AVLTree.class));
    }
    
    @Test
    public void testConstructorNode() {
        tree = new AVLTree<String>(new Node<String>("Root"));
        assertThat(tree, instanceOf(AVLTree.class));
    }
    
    @Test
    public void testAddElement() {
        Node<String> child1 = new Node<String>("Child 1");
        Node<String> child2 = new Node<String>("Child 2");
        assertFalse(tree.hasElement("Root"));
        tree.addElement("Root");
        assertTrue(tree.hasElement("Root"));
        assertEquals(0, tree.getRoot().getBalance());
        assertEquals(0, tree.getRoot().getHeight());
        assertEquals(1, tree.getNumElements());
        tree.addElement(child1);
        assertEquals(-1, tree.getRoot().getBalance());
        assertEquals(1, tree.getRoot().getHeight());
        assertEquals(2, tree.getNumElements());
        tree.addElement(child2);
        assertEquals(child2, tree.getRoot());
        assertEquals("Root", tree.getRoot().getRightChild().getData());
        assertEquals(null, tree.getRoot().getRightChild().getLeftChild());
        assertEquals(null, tree.getRoot().getRightChild().getRightChild());
        assertEquals(child1, tree.getRoot().getLeftChild());
        assertEquals(null, child1.getLeftChild());
        assertEquals(null, child1.getRightChild());
        assertEquals(0, tree.getRoot().getBalance());
        assertEquals(1, tree.getRoot().getHeight());
        assertEquals(3, tree.getNumElements());
    }
    
    @Test
    public void testFindElementString() {
        tree.addElement("Root");
        assertEquals("Root", tree.findElement("Root").getData());
    }
    
    @Test
    public void testFindElementNode() {
        Node<String> root = new Node<String>("Root");
        tree.addElement(root);
        assertEquals("Root", tree.findElement(root).getData());
    }
    
    @Test
    public void testRemoveElement() {
        Node<String> root = new Node<String>("Root");
        Node<String> child1 = new Node<String>("Child 1");
        Node<String> child2 = new Node<String>("Child 2");
        tree.addElement(root);
        tree.addElement(child1);
        tree.addElement(child2);
        assertTrue(tree.hasElement(root));
        assertTrue(tree.hasElement(child1));
        assertTrue(tree.hasElement(child2));
        assertEquals(child2, tree.getRoot());
        assertEquals(child1, tree.getRoot().getLeftChild());
        assertEquals(child2, tree.getRoot().getLeftChild().getParent());
        assertEquals(root, tree.getRoot().getRightChild());
        assertEquals(child2, tree.getRoot().getRightChild().getParent());
        tree.removeElement(root);
        assertFalse(tree.hasElement(root));
    }
}
